package com.jp.refreshlocalcacheclient.net.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.net.InetSocketAddress;

/**
 * @Author: jipeng
 * @Description:
 * @Date: Created in 2020/5/12 19:23
 */
@Service
@EnableScheduling
@ConditionalOnProperty(name = {"refres.local.cache.server.host","refres.local.cache.server.port"})
public class ClientServer {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    //配置提供
    @Value("${refres.local.cache.server.host}")
    private String host;

    //配置提供
    @Value("${refres.local.cache.server.port}")
    private int port;



    /**
     * 标记服务在启动
     */
    private boolean clientIsStart = false;

    /**
     * 启动服务
     * @return
     */
    public ChannelFuture start() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup(1);

        Bootstrap b = new Bootstrap();
        try {
            b.group(group)
            .channel(NioSocketChannel.class)
            .remoteAddress(new InetSocketAddress(host, port))
            .handler(new EchoClientHandlerInitializer());

            ChannelFuture cf = b.connect().sync();

            //设置服务已启动
            clientStart();
            return cf.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync();
        }
    }

    /**
     *  客户端重试机制
     *  1分钟执行一次，防止服务端停止后恢复，客户端需要主动连接
     */
    @Scheduled(fixedDelay = 60000)
    public void loopExecute(){
        //服务启动状态不执行后续逻辑
        if(clientIsStart){
            return;
        }

        logger.info("refresh local cache client start");
        try{
            start().addListener((f) -> clientStop() );
        }catch (Exception e){
            logger.error("cache client netty start error = > {}", ExceptionUtils.getStackTrace(e));
            clientStop();
        }
    }

    /**
     * 客户端启动
     */
    private void clientStart(){
        clientIsStart = true;
    }

    /**
     * 客户端停止
     */
    private void clientStop(){
        clientIsStart = false;
    }

}
